package com.mushuilingfeng.ddd.user.domain.user.entity;

import cn.hutool.core.util.StrUtil;
import com.mushuilingfeng.ddd.framework.factory.DomainEventFactory;
import com.mushuilingfeng.ddd.framework.factory.DomainRepositoryFactory;
import com.mushuilingfeng.ddd.framework.factory.DomainServiceFactory;
import com.mushuilingfeng.ddd.user.domain.base.*;
import com.mushuilingfeng.ddd.user.domain.user.enums.UserStatusEnum;
import com.mushuilingfeng.ddd.user.domain.user.event.UserLockedEvent;
import com.mushuilingfeng.ddd.user.domain.user.repository.IUserRepository;
import com.mushuilingfeng.ddd.user.domain.user.service.IPasswordService;
import com.mushuilingfeng.ddd.user.domain.user.vo.UserPersonInfo;
import com.mushuilingfeng.ddd.user.domain.util.TelUtil;
import lombok.Data;
import lombok.EqualsAndHashCode;

/**
 * @author
 * @date 2024/9/14
 */
@EqualsAndHashCode(callSuper = true)
@Data
public class User extends BaseEntity {
    private UserLoginAccount loginAccount;
    private String telephone;
    private String nickName;
    private GenderEnum gender;
    private UserStatusEnum status;
    private UserPersonInfo personInfo;
    
    @Override
    public void simpleCheckParams() {
        super.simpleCheckParams();
        if (loginAccount == null) {
            throw new DomainArgumentException(Ii8nCode.LOGIN_ACCOUNT_CANNOT_BE_EMPTY);
        }
        loginAccount.simpleCheckParams();
        if (StrUtil.isBlankIfStr(telephone)) {
            throw new DomainArgumentException(Ii8nCode.TEL_CANNOT_BE_EMPTY);
        }
        if (StrUtil.isBlankIfStr(nickName)) {
            throw new DomainArgumentException(Ii8nCode.NICK_NAME_CANNOT_BE_EMPTY);
        }
    }
    
    @Override
    public void saveNew() {
        super.saveNew();
        if (null == gender) {
            gender = GenderEnum.UNKNOWN;
        }
        status = UserStatusEnum.OPEN;
        IUserRepository userRepository = DomainRepositoryFactory.getRepository(IUserRepository.class);
        // 检查手机号是否被占用
        if (null != userRepository.findByLoginAccount(loginAccount.getLoginAccount())) {
            throw new BusinessException(Ii8nCode.ACCOUNT_IS_EXIST);
        }
        // 检查登陆账号是否被占用
        if (null != userRepository.findByTelephone(telephone)) {
            throw new BusinessException(Ii8nCode.TEL_IS_EXIST);
        }
        // 密码加密
        loginAccount.setLoginPassword(DomainServiceFactory.getDomainService(IPasswordService.class).encrypt(loginAccount.getLoginPassword()));
        userRepository.save(this);
    }
    
    /**
     * 安全打码
     */
    public void mark() {
        loginAccount = null;
        telephone = TelUtil.mask(telephone);
    }
    
    public void updatePassword(String oldPassword, String newPassword) {
        if (!loginAccount.getLoginPassword().equals(DomainServiceFactory.getDomainService(IPasswordService.class).encrypt(oldPassword))) {
            throw new BusinessException(Ii8nCode.ACCOUNT_OR_PASSWORD_ERROR);
        }
        loginAccount.updatePassword(DomainServiceFactory.getDomainService(IPasswordService.class).encrypt(newPassword));
    }
    
    public void updateNickName(String nickName) {
        this.nickName = nickName;
        DomainRepositoryFactory.getRepository(IUserRepository.class).updateNickName(id, nickName);
    }
    
    public void updateTelephone(String telephone) {
        this.telephone = telephone;
        DomainRepositoryFactory.getRepository(IUserRepository.class).updateTelephone(id, telephone);
    }
    
    public void updatePersonInfo(UserPersonInfo personInfo) {
        this.personInfo = personInfo;
        DomainRepositoryFactory.getRepository(IUserRepository.class).updatePersonInfo(id, personInfo);
    }
    
    public void lock() {
        setStatus(UserStatusEnum.LOCK);
        DomainRepositoryFactory.getRepository(IUserRepository.class).updateStatus(id, status);
        // 发布事件
        DomainEventFactory.getEventPublisher().publish(new UserLockedEvent(id));
    }
    
    public void unlock() {
        setStatus(UserStatusEnum.OPEN);
        DomainRepositoryFactory.getRepository(IUserRepository.class).updateStatus(id, status);
    }
    
}
